package com.qcrud.core;

import lombok.extern.slf4j.Slf4j;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class SqlStatement implements AutoCloseable {
    private final String sql;
    private StatementContext ctx;
    private PreparedStatement ps;

    public SqlStatement(StatementContext ctx, String sql, PreparedStatement ps) {
        this.ctx = ctx;
        this.sql = sql;
        this.ps = ps;
    }

    public SqlStatement bindArgs(Object... args) {
        Binding binding = this.ctx.getBinding();
        binding.clear();
        int position = 1;
        for (Object arg : args) {
            binding.addPosition(position++, arg);
        }
        return this;
    }

    public boolean execute() throws SQLException {
        /**
         * 绑定 SQL 执行参数
         */
        this.binding();
        /**
         * 如果第一个结果是 ResultSet 对象，则返回 true
         * 如果第一个结果是更新计数或者没有结果，则返回 false
         */
        boolean result = ps.execute();
        if (log.isDebugEnabled()) {
            log.debug("execute sql: {} ; result: {}", sql.trim(), result);
        }
        return result;
    }

    public void binding() {
        Binding binding = this.ctx.getBinding();
        binding.positions.forEach((k, v) -> {
            try {
                ps.setObject(k, v);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        });
    }

    public List<Map<String, Object>> executeQuery() throws SQLException {
        this.binding();
        List<Map<String, Object>> list = new ArrayList<>();
        ResultSet rs = ps.executeQuery();
        if (null != rs) {
            ResultSetMetaData rsm = rs.getMetaData();
            int rows = rsm.getColumnCount();
            while (rs.next()) {
                Map<String, Object> rowData = new HashMap<>();
                String sKey;
                String sValue;
                for (int j = 1; j <= rows; j++) {
                    sKey = (rsm.getColumnName(j)).trim();
                    String tString = rs.getString(j);
                    if (tString == null) {
                        sValue = "";
                    } else {
                        sValue = tString.trim();
                        if (sValue == null) sValue = "";
                    }
                    rowData.put(sKey, sValue);
                }
                list.add(rowData);
            }
        }
        return list;
    }

    public int executeUpdate() throws SQLException {
        this.binding();
        return ps.executeUpdate();
    }

    @Override
    public void close() throws Exception {

    }
}
